home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / pascal / totdoc.zip / CHAPT6.TXT < prev    next >
Text File  |  1991-02-11  |  44KB  |  1,062 lines

  1.                                                                         Keyboard
  2.                                                                                &
  3.                                                                            Mouse
  4.                                                                            Input
  5.  
  6.  
  7.  
  8.          "The computer is down. I hope it's something serious."
  9.  
  10.                                                                Stanton Delaplane
  11.  
  12.          The totINPUT unit includes two objects for managing the mouse and key-
  13.          board. KeyOBJ is the main object for determining mouse and keyboard
  14.          activity. MouseOBJ controls the location and shape of the mouse cursor.
  15.          Mouse support is provided for Microsoft two-button, Logitech three-
  16.          button, and 100% compatible mice.
  17.  
  18.  
  19. Getting Keyboard and Mouse Input
  20.  
  21.          totINPUT includes a global instance KEY of type KeyOBJ. In the same way
  22.          that the instance SCREEN is used for all screen writes, the KEY
  23.          instance should be used for all keyboard and mouse polling. Key
  24.          includes methods for determining which key or mouse button was pressed,
  25.          checking the status of the Alt/Ctrl/Shift keys, controlling the
  26.          Num/Scroll/Caps lock keys, setting the keyboard repeat rate, and
  27.          stuffing the keyboard buffer.
  28.          There are also two special user hooks which provide easy ways to cus-
  29.          tomize your program. The idle hook allows you to perform some action
  30.          (like displaying a ticking clock) while the program is idle waiting for
  31.          user input. The character hook allows you to intercept every user
  32.          action, and is called every time a key is pressed or a mouse button is
  33.          clicked.
  34.  
  35.  
  36. Setting Mouse Methods
  37.  
  38.          Users of TechnoJock's Turbo Toolkit (TTT) may recall that the input
  39.          routines supported an "invisible" mouse cursor. If the user moved the
  40.          mouse while a program was waiting for a key press, a special code was
  41.          returned which indicated that the mouse had been moved either up, down,
  42.          left or right. Most of the TTT units would respond to the mouse move-
  43.          ment as though a cursor key had been pressed.
  44.          TechnoJock's Object Toolkit provides much more extensive mouse support.
  45.          However, if you want to make your programs respond like the original
  46.          TTT, you can with the following SetMouseMethod method:
  47.  
  48.  
  49.          SetMouseMethod(Method:byte);
  50.  
  51.  
  52. 6-2                                                                 User's Guide
  53. --------------------------------------------------------------------------------
  54.  
  55.          This method instructs the Toolkit on which form of mouse support to
  56.          provide. If a 0 is passed, or if there is no mouse detected, the object
  57.          will ignore any mouse activity. If a 1 is passed, an "invisible" mouse
  58.          will be supported, and if a 2 is passed, full mouse support is enabled.
  59.          If you want to temporarily disable mouse support, set the mouse method
  60.          to 0, which can later be set back to 1 or 2.
  61.  
  62.  
  63.          When the mouse method is set to 1, the following two methods control
  64.          how much the mouse must be moved before the movement is detected:
  65.  
  66.  
  67.          SetHoriz(Sensitivity:byte);
  68.          This method is passed the number of characters that the mouse cursor
  69.          must be moved horizontally before a MouseLeft or MouseRight code is
  70.          returned.
  71.  
  72.  
  73.          SetVert(Sensitivity:byte);
  74.          This method is passed the number of characters that the mouse cursor
  75.          must be moved vertically before a MouseUp or MouseDown code is
  76.          returned.
  77.  
  78.  
  79.  
  80. Determining User Input
  81.          The heart of the KeyOBJ object is the GetInput method. GetInput pauses
  82.          program execution and waits for the user to press a key, or click a
  83.          mouse button (or move the mouse, if the MouseMethod is set to 1). The
  84.          user action can be determined by calling the functions Lastkey, LastX
  85.          and LastY. These functions return the key/button(s) which were pressed,
  86.          and the (X,Y) location of the mouse when the action took place, respec-
  87.          tively.
  88.  
  89.          Another method, GetKey, automatically calls GetInput, and returns the
  90.          user action code -- this saves calling GetInput followed by LastKey.
  91.          The method DelayKey is like GetInput, but will only pause for user
  92.          input for a specified number of milliseconds. This method is useful for
  93.          displaying temporary messages and the like. If a key has not been
  94.          pressed after a specified time period, Lastkey is updated with a value
  95.          of 0.
  96.  
  97.          Unlike Turbo Pascal, the Toolkit uses a WORD sized variable to record
  98.          the user activity. As well as supporting the standard keyboard, KeyOBJ
  99.          reports mouse button activity, as well as many special key combina-
  100.          tions, e.g. Alt-TAB. Refer to table 6.1 for a full list of the KeyOBJ
  101.          action codes. Some of the action codes listed in the table are raised
  102.  
  103.  
  104.  
  105. Keyboard & Mouse                                                             6-3
  106. --------------------------------------------------------------------------------
  107.  
  108.          by totWIN objects which indicate that the mouse was clicked on a spe-
  109.          cial window icon. Refer to chapter 7: Using Windows for further infor-
  110.          mation.
  111.  
  112.  
  113.  
  114. 6-4                                                                 User's Guide
  115. --------------------------------------------------------------------------------
  116.  
  117. Table 6.1
  118. Key Action Codes
  119.  
  120.            Key  Norm   Shift  Alt    Ctrl     Key   Norm   Shift  Alt    Ctrl
  121.            a    97     65     286    1        F1    315    340    360    350
  122.            b    98     66     304    2        F2    316    341    361    351
  123.            c    99     67     302    3        F3    317    342    362    352
  124.            d    100    68     288    4        F4    318    343    363    353
  125.            e    101    69     274    5        F5    319    344    364    354
  126.            f    102    70     289    6        F6    320    345    365    355
  127.            g    103    71     290    7        F7    321    346    366    356
  128.            h    104    72     291    8        F8    322    347    367    357
  129.            i    105    73     279    9        F9    323    348    368    358
  130.            j    106    74     292    10       F10   324    349    369    359
  131.            k    107    75     293    11       F11   389    391    395    393
  132.            l    108    76     294    12       F12   390    392    396    394
  133.            m    109    77     306    13
  134.            n    110    78     305    14       BkSp  8      8      270    127
  135.            o    111    79     280    15       Up    328    428    408    397
  136.            p    112    80     281    16       Down  336    436    416    401
  137.            q    113    81     272    17       Left  331    431    411    371
  138.            r    114    82     275    18       Right 333    433    413    372
  139.            s    115    83     287    19       End   335    435    415    373
  140.            t    116    84     276    20       Home  327    427    407    375
  141.            u    117    85     278    21       PgUp  329    429    409    388
  142.            v    118    86     303    22       PgDn  337    437    417    374
  143.            w    119    87     273    23       Ins   338    261    418    260
  144.            x    120    88     301    24       Del   339    263    419    262
  145.            y    121    89     277    25       Tab   9      271    421    404
  146.            z    122    90     300    26       Esc   27     27     257    27
  147.                                               Enter 13     13     284    10
  148.            1 !  49     33     376    -
  149.            2 @  50     64     377    259      , <   44     60     307    -
  150.            3 #  51     35     378    -        . >   46     62     308    -
  151.            4 $  52     36     379    -        / ?   47     63     309    -
  152.            5 %  53     37     380    -        ; :   59     58     295    -
  153.            6 ^  54     94     381    30       ' "   39     34     296    -
  154.            7 &  55     38     382    -        [ {   91     123    282    27
  155.            8 *  56     42     383    -        ] }   93     125    283    29
  156.            9 (  57     40     384    -        \ |   92     124    299    28
  157.            0 )  48     41     385    -
  158.            - _  45     95     386    31
  159.            = +  61     43     387    -
  160.  
  161.  
  162.  
  163.  
  164. Keyboard & Mouse                                                             6-5
  165. --------------------------------------------------------------------------------
  166.  
  167. Table 6.1
  168. Key Action Codes
  169. (Contd.)
  170.  
  171.            Mouse Action     Code           Window Action           Code
  172.            Left Click       513            Close Icon Selected     600
  173.            Right Click      514            Window Moved            601
  174.            Middle Click     515            Window Resized          602
  175.            Left + Right     516            Scroll Bar Up           610
  176.            Left + Middle    517            Scroll Bar Down         611
  177.            Middle + Right   518            Scroll Bar Left         612
  178.            All three        519            Scroll Bar Right        613
  179.            Left Double      523            Vertical Elevator       614
  180.            Right Double     524            Horizontal Elevator     615
  181.            Middle Double    525
  182.  
  183.            Mouse Up         584
  184.            Mouse Down       592
  185.            Mouse Left       589
  186.            Mouse Right      587
  187.  
  188.  
  189.  
  190.          Note: the upper ASCII characters are also returned if the user holds
  191.          down the Alt key and presses the 3-digit ASCII code on the numeric
  192.          keypad, or if an international code page is active. In other words, the
  193.          input routines fully support international characters, line drawing,
  194.          and all other extended ASCII characters.
  195.  
  196.  
  197.          In most cases, you will use the global instance Key to determine user
  198.          input. However, if you want to use an independent instance, make sure
  199.          you initialize the instance by calling the INIT method.
  200.          The function method Extended will return true if an extended keyboard
  201.          is installed.
  202.  
  203.          Listed below is the syntax for the user input methods:
  204.  
  205.          GetInput;
  206.  
  207.          Pauses program execution until a key or mouse button is pressed.
  208.  
  209.          GetKey: word;
  210.  
  211.          Pauses program execution until a key or mouse button is pressed, and
  212.          returns a word value indicating the user action, (see Table 6.1)
  213.  
  214.          LastKey: word;
  215.  
  216.  
  217.  
  218. 6-6                                                                 User's Guide
  219. --------------------------------------------------------------------------------
  220.  
  221.          Returns a word value indicating the last user action, (see Table 6.1)
  222.  
  223.  
  224.          LastChar: char;
  225.          If the action code of the LastKey was less than 256, the character
  226.          equivalent of the code is returned, otherwise a #0 is returned.
  227.  
  228.  
  229.          LastX: byte;
  230.          Returns the X Coordinate of the mouse cursor when the last key action
  231.          was recorded.
  232.  
  233.  
  234.          LastY: byte;
  235.          Returns the Y Coordinate of the mouse cursor when the last key action
  236.          was recorded.
  237.  
  238.  
  239.          DelayKey(Mills:longint);
  240.          This function is similar to GetInput, except that the method will only
  241.          wait for Mills milliseconds. If the user is not active in the specified
  242.          period, a #0 is recorded as the last key.
  243.  
  244.  
  245.          Extended:boolean;
  246.          This function method returns true if the system has an extended key-
  247.          board installed.
  248.  
  249.  
  250.          The following example shows how you might pause for some user action,
  251.          and then check the pressed key to decide which routines to execute
  252.          next:
  253.  
  254.                   ...
  255.                   Key.GetInput
  256.                   case Key.LastKey of
  257.                     27:  EscapeRoutine;
  258.                     13:  EnterRoutine;
  259.                     513: LeftButtonRoutine(Key.LastX,Key.LastY);
  260.                     ...
  261.                   end; {case}
  262.                   ...
  263.  
  264.          The following example, DEMIN1.PAS, repeatedly waits for some user
  265.          action, and displays the value of each action code:
  266.  
  267.          Program DemoInputOne;
  268.          {DEMIN1}
  269.  
  270.  
  271. Keyboard & Mouse                                                             6-7
  272. --------------------------------------------------------------------------------
  273.  
  274.          Uses CRT,
  275.               totINPUT;
  276.  
  277.          begin
  278.             Clrscr;
  279.             Writeln('Press any key or mouse button combination.
  280.                      (Esc to quit)');
  281.             Key.SetDouble(true);
  282.             repeat
  283.                Key.GetInput;
  284.                GotoXY(1,2);
  285.                Write('You pressed key: ',Key.LastKey,'    ');
  286.             until Key.LastKey = 27;
  287.          end.
  288.  
  289.  
  290.  
  291.  
  292.            Note: The Toolkit reports double-clicking on any of the mouse but-
  293.            tons.
  294.  
  295.            You may have used some software products which make the user
  296.            double-click the mouse at "lightning" speed. This problem occurs
  297.            because the software wants to respond as soon as possible to any
  298.            mouse activity. So, when a button is clicked, the software doesn't
  299.            wait around for very long to see if the same button has been
  300.            clicked again. If you are not quick enough, a double-click is
  301.            reported as one or two single clicks of the same button.
  302.  
  303.            The Toolkit has the same design dilemma: fast response, with
  304.            enough time so a non-athlete can double-click a button! The Tool-
  305.            kit solution is to allow you to set whether the system should wait
  306.            for a double-click. KeyOBJ includes the method SetDouble, which is
  307.            passed a boolean parameter. Pass a TRUE parameter to allow a
  308.            little extra time for double-clicks. If you don't care about
  309.            double-clicks, call SetDouble(false);. You can freely switch
  310.            between the two states throughout the program. By default, Key
  311.            does not pause for double-clicks.
  312.  
  313.            The function method GetDouble returns the current double-click
  314.            setting.
  315.  
  316.            You can experiment with the impact of the SetDouble method by
  317.            trying the above example with SetDouble enabled and disabled.
  318.  
  319.  
  320.  
  321. 6-8                                                                 User's Guide
  322. --------------------------------------------------------------------------------
  323.  
  324. Accessing Ctrl, Alt and Shift
  325.  
  326.          KeyOBJ supports a wide variety of special key combinations like Alt-
  327.          Backspace and Ctrl-PgUp. Sometimes, however, you may want to know if
  328.          one of the shifting keys is being pressed on its own. GetInput will not
  329.          respond when Alt, Ctrl or either Shift key is pressed. It waits for a
  330.          standard alphanumeric key to be pressed.
  331.          KeyOBJ does, however, provide the following five methods to let you
  332.          check the status of these special shifting keys:
  333.  
  334.  
  335.          AltPressed:boolean;
  336.          Returns true if the Alt key is being held down.
  337.  
  338.  
  339.          CtrlPressed: boolean;
  340.          Returns true if the Ctrl key is being held down.
  341.  
  342.  
  343.          LeftShiftPressed: boolean;
  344.          Returns true if the left Shift key is being held down.
  345.  
  346.  
  347.          RightShiftPressed: boolean;
  348.          Returns true if the right Shift key is being held down.
  349.  
  350.  
  351.          ShiftPressed: boolean;
  352.          Returns true if either Shift key is being held down.
  353.  
  354.  
  355.          These methods are useful if you want to display an indicator which
  356.          illuminates when the special keys are pressed. The demo program,
  357.          DEMIN2.PAS, discussed in the next section, illustrates this technique.
  358.  
  359. Accessing Num, Scroll and Caps Lock
  360.  
  361.          The KeyOBJ provides the following six methods for determining and
  362.          changing the status of the Num Lock, Scroll Lock and Caps Lock keys:
  363.  
  364.          SetCaps(On:boolean);
  365.  
  366.          Pass TRUE to turn on the Caps Lock key, or FALSE to turn it off.
  367.  
  368.          SetNum(On:boolean);
  369.  
  370.          Pass TRUE to turn on the Num Lock key, or FALSE to turn it off.
  371.  
  372. Keyboard & Mouse                                                             6-9
  373. --------------------------------------------------------------------------------
  374.  
  375.          SetScroll(On:boolean);
  376.  
  377.          Pass TRUE to turn on the Scroll Lock key, or FALSE to turn it off.
  378.  
  379.          GetCaps:boolean;
  380.  
  381.          Returns TRUE if the Caps Lock is on, and FALSE if it is off.
  382.  
  383.          GetNum:boolean;
  384.  
  385.          Returns TRUE if the Num Lock is on, and FALSE if it is off.
  386.  
  387.          GetScroll:boolean;
  388.  
  389.          Returns TRUE if the Scroll Lock is on, and FALSE if it is off.
  390.  
  391.  
  392.          The following demo program, DEMIN2.PAS, shows how to use the shifting
  393.          and locking keys.
  394.          Program DemoInputTwo;
  395.          {DEMIN2}
  396.  
  397.          Uses CRT,
  398.               totINPUT, totFAST;
  399.          begin
  400.             with Screen do
  401.             begin
  402.                 Clear(31,' ');
  403.                 PartClear(1,23,80,25,94,' ');
  404.                 WritePlain(10,5,'Press Num, Scroll, Caps Lock,
  405.                                  or hold down the Alt,');
  406.                 WritePlain(10,6,'Ctrl, Left/Right Shift keys.
  407.                                  The active keys will be');
  408.                 WritePlain(10,7,'highlighted at the foot of the
  409.                                  display.');
  410.                 WritePlain(10,9,'Any other key quits.');
  411.                 with Key do
  412.                 begin
  413.                    SetCaps(true);
  414.                    SetNum(true);
  415.                    SetScroll(true);
  416.                    repeat
  417.                       if GetCaps then
  418.                          WritePlain(40,24,'CAPS')
  419.                       else
  420.                          WritePlain(40,24,'    ');
  421.                       if GetNum then
  422.                          WritePlain(45,24,'NUM')
  423.  
  424.  
  425.  
  426. 6-10                                                                User's Guide
  427. --------------------------------------------------------------------------------
  428.  
  429.                       else
  430.                          WritePlain(45,24,'   ');
  431.                       if GetScroll then
  432.                          WritePlain(50,24,'SCROLL')
  433.                       else
  434.                          WritePlain(50,24,'      ');
  435.                       if AltPressed then
  436.                          WritePlain(60,24,'Alt')
  437.                       else
  438.                          WritePlain(60,24,'   ');
  439.                       if CtrlPressed then
  440.                          WritePlain(65,24,'Ctrl')
  441.                       else
  442.                          WritePlain(65,24,'    ');
  443.                       if LeftShiftPressed then
  444.                          WritePlain(70,24,'L-^X')
  445.                       else
  446.                          WritePlain(70,24,'   ');
  447.                       if RightShiftPressed then
  448.                          WritePlain(75,24,'R-^X')
  449.                       else
  450.                          WritePlain(75,24,'   ');
  451.                    until KeyPressed;
  452.                    SetCaps(false);
  453.                    SetNum(false);
  454.                    SetScroll(false);
  455.                 end;
  456.             end;
  457.          end.
  458.  
  459.  
  460.  
  461.            Note: The methods for setting and getting the status of the lock-
  462.            ing keys will only function on 100% IBM BIOS compatible systems.
  463.  
  464.  
  465.  
  466.  
  467. Setting the Keyboard Repeat Rate, and Clicking
  468.          The PC keyboards support a typematic effect i.e. holding a key pressed
  469.          down has the same effect as pressing the key multiple times. By
  470.          default, a key must be held down for about half a second before the
  471.          repetition commences, and then about ten characters per second are
  472.          sent. Most users think this repeat rate is too slow (especially for
  473.          cursor movement) and the Toolkit provides a way of changing it.
  474.  
  475.  
  476.  
  477. Keyboard & Mouse                                                            6-11
  478. --------------------------------------------------------------------------------
  479.  
  480.          Commencing with the IBM-AT, the ROM BIOS keyboard services provided a
  481.          way to change the typematic rate. The earliest ROM BIOS to feature
  482.          configurable typematic delays was 11/15/85. The following three KeyOBJ
  483.          methods can be used to modify the typematic rate on systems with the
  484.          required BIOS:
  485.  
  486.  
  487.          SetFast;
  488.          Set the typematic rate to a fast 30 characters per second, i.e. there
  489.          is very little delay between repeats.
  490.  
  491.  
  492.          SetSlow;
  493.          Sets the typematic rate to 5 characters per second.
  494.  
  495.  
  496.          SetRepeatRate(QSDelay,Rate:byte);
  497.          This method allows you to explicitly set the typematic rate. The first
  498.          parameter accepts a value between 1 and 4, and indicates the number of
  499.          quarter seconds delay before the key commences repeating, e.g. 3 repre-
  500.          sents a 750 millisecond delay. The second parameter indicates the
  501.          repeat rate, and accepts a value between 0 and 31. The following table
  502.          shows the repeat rate parameter followed by the corresponding character
  503.          per second repeat rate:
  504.  
  505.            0   30.0    7   16.0    14  8.6     21  4.6      28  2.5
  506.            1   26.7    8   15.0    15  8.0     22  4.3      29  2.3
  507.            2   24.0    9   13.3    16  7.5     23  4.0      30  2.1
  508.            3   21.8    10  12.0    17  6.7     24  3.7      31  2.0
  509.            4   20.0    11  10.9    18  6.0     25  3.3
  510.            5   18.5    12  10.0    19  5.5     26  3.0
  511.            6   17.1    13  9.2     20  5.0     27  2.7
  512.  
  513.          Note: keyboard ROM BIOS provides no way of determining the current
  514.          typematic rate setting.
  515.  
  516.          The typematic rate is set in BIOS, and so the methods will affect the
  517.          typematic rate for the rest of the session, even after the program has
  518.          terminated.
  519.  
  520.  
  521.          Do you remember how typewriters used to click? Well, the Toolkit pro-
  522.          vides a way of emitting an electronic click every time a key is
  523.          pressed. The following method can be used to control keyboard clicking:
  524.  
  525.          SetClick(On:boolean);
  526.  
  527.          Pass TRUE to activate clicking, or FALSE to switch it off. By default,
  528.          clicking is off.
  529.  
  530.  
  531. 6-12                                                                User's Guide
  532. --------------------------------------------------------------------------------
  533.  
  534.          The demo program DEMBR1.PAS is designed to illustrate the BrowseOBJ
  535.          object which is discussed in chapter 9. There are, however, some Key
  536.          statements included. Execute the demo program and experiment with the
  537.          typematic rate.
  538.  
  539.  
  540.  
  541. Using the Keyboard Buffer
  542.          The KeyOBJ uses an internal buffer for storing keystrokes. The sole
  543.          purpose of this buffer is to allow you to force characters into the
  544.          buffer using the methods StuffBuffer and StuffBufferStr. GetInput (and
  545.          therefore GetKey/GetChar) also checks the characters in the buffer
  546.          before checking the keyboard.
  547.  
  548.          By default, the size of the buffer is 30 characters, but this can be
  549.          easily modified by changing the StuffBufferSize constant at the top of
  550.          the totINPUT unit. Listed below is the syntax of the buffer related
  551.          methods:
  552.  
  553.          StuffBuffer(W:word);
  554.  
  555.          This forces a key into the keyboard buffer. The parameter passed is the
  556.          word value of the character, as detailed in Table 6.1.
  557.  
  558.          StuffBufferStr(Str:string);
  559.  
  560.          This stuffs characters (with ASCII values in the range 0 to 255) into
  561.          the keyboard buffer. This method is provided as a convenience to save
  562.          making multiple calls to StuffBuffer (one call for every character in
  563.          the string).
  564.  
  565.          FlushBuffer;
  566.  
  567.          Erases all the keys in the keyboard buffer.
  568.  
  569.          KeyPressed: boolean;
  570.  
  571.          Use this method in preference to Turbo Pascal's Keypressed function,
  572.          because it checks the internal buffer as well as the keyboard buffer.
  573.  
  574.  
  575.          The keyboard stuffing capabilities form the framework for a simple but
  576.          elegant macro facility. A full example, DEMIN3.PAS, illustrates this
  577.          concept and is discussed in the next section.
  578.  
  579.  
  580.  
  581. Keyboard & Mouse                                                            6-13
  582. --------------------------------------------------------------------------------
  583.  
  584. Assigning Keyboard Hooks
  585.  
  586.          The KeyOBJ object allows you to assign a procedure which will be called
  587.          while the program is idle and waiting for the user to press a key.
  588.          Similarly, the object allows you to assign a procedure which will be
  589.          called every time a character is pressed. These two types of procedures
  590.          are referred to as an Idle Hook and a Pressed Hook, respectively.
  591.          IMPORTANT NOTE: If you write to the display from a hooked procedure,
  592.          you need to be aware that the active routine may have the display
  593.          window set. To avoid any problems, use the Screen method SetWinIgnore
  594.          to temporarily disable the window setting. Refer to page 5-17 for fur-
  595.          ther details.
  596.  
  597.  
  598. Idle Hook
  599.  
  600.          An idle hook is an external procedure which will be repeatedly called
  601.          while the program is waiting for the user to input data. A good use for
  602.          an idle hook is to display a ticking clock that is always updated, or
  603.          to show the status of the "shift" and "lock" keys.
  604.          All you have to do is create a procedure following some specific rules,
  605.          and then call the method Key.AssignIdleHook to instruct the Key object
  606.          to call your procedure.
  607.  
  608.          For a procedure to be eligible as an idle hook it must adhere to the
  609.          following three rules:
  610.          Rule 1     The procedure must be declared as a FAR procedure. This can
  611.                     be achieved by preceding the procedure with a {$F+} compiler
  612.                     directive, and following the procedure with a {$F-} direc-
  613.                     tive. Alternatively, Turbo 6 users can use the new keyword
  614.                     FAR following the procedure statement.
  615.  
  616.          Rule 2     The procedure must be declared with no (nada/zero/none)
  617.                     passed parameters.
  618.          Rule 3     The procedure must be at the root level, i.e. the procedure
  619.                     cannot be nested within another procedure.
  620.  
  621.          The following procedure declaration follows these rules:
  622.                   {$F+}
  623.                   procedure MyIdleHook;
  624.                   .....{procedure statements}
  625.                   end;
  626.                   {$F-}
  627.  
  628.  
  629.          The following method AssignIdleHook is then called to instruct the
  630.          Toolkit to call your procedure while the system is waiting for input:
  631.  
  632.  
  633.  
  634.  
  635. 6-14                                                                User's Guide
  636. --------------------------------------------------------------------------------
  637.  
  638.          AssignIdleHook(PassedProc:InputIdleProc);
  639.  
  640.          This method is passed the procedure name of a procedure declared using
  641.          the rules outlined above.
  642.  
  643.  
  644.          Your procedure will be continually called while your program is waiting
  645.          for user input, so make sure that the procedure is compact and effi-
  646.          cient. If your procedure involves too many tasks, the program will slow
  647.          down considerably during input. If you want to call an extended task
  648.          like a background print program, you must continually check the
  649.          Key.Keypressed function method and suspend your procedure when it
  650.          returns true.
  651.          If subsequently, you want to remove your idle hook, execute the follow-
  652.          ing:
  653.  
  654.                   Key.AssignIdleHook(NoInputIdleHook);
  655.  
  656.  
  657.  
  658.  
  659. Pressed Hook
  660.          A pressed hook is a procedure which is called every time a key is
  661.          pressed or a mouse button is clicked. This is particularly useful for
  662.          trapping special keys like [KEYCAP] for help, or for building keyboard
  663.          macros.
  664.  
  665.          All you have to do is create a procedure following some specific rules,
  666.          and then call the method Key.AssignPressedHook to instruct the Key
  667.          object to call your procedure each time a key is pressed.
  668.          For a procedure to be eligible as a pressed hook it must adhere to the
  669.          following three rules:
  670.  
  671.          Rule 1     The procedure must be declared as a FAR procedure. This can
  672.                     be achieved by preceding the procedure with a {$F+} compiler
  673.                     directive, and following the procedure with a {$F-} direc-
  674.                     tive. Alternatively, Turbo 6 users can use the new keyword
  675.                     FAR following the procedure statement.
  676.          Rule 2     The procedure must be declared with one passed parameter,
  677.                     and this parameter must be a variable parameter of type
  678.                     word, e.g. (var W:word);.
  679.  
  680.          Rule 3     The procedure must be at the root level, i.e. the procedure
  681.                     cannot be nested within another procedure.
  682.          The following procedure declaration follows these rules:
  683.  
  684.  
  685. Keyboard & Mouse                                                            6-15
  686. --------------------------------------------------------------------------------
  687.  
  688.                   {$F+}
  689.                   procedure MyPressedHook(var K:word);
  690.                   .....{procedure statements}
  691.                   end;
  692.                   {$F-}
  693.  
  694.  
  695.          The following method AssignPressedHook is then called to instruct the
  696.          Toolkit to call your procedure when the system receives input:
  697.  
  698.          AssignPressedHook(PassedProc:InputPressedProc);
  699.  
  700.          This method is passed the procedure name of a procedure declared using
  701.          the rules outlined above.
  702.  
  703.  
  704.          The parameter passed to your procedure is the value of the key (or
  705.          mouse button) just pressed, as detailed in Table 6.1. Test the value of
  706.          the parameter, and decide what action to take. As with the idle hook,
  707.          keep the hooked procedure small and efficient to avoid program execu-
  708.          tion delays.
  709.          When your procedure terminates, the character is then processed in the
  710.          normal manner by your program. If you want the character to be ignored,
  711.          set the passed parameter value to 0. You can also use this facility to
  712.          swap the meaning of keys. For example, the following code fragment
  713.          intercepts the double-quote and replaces it with a single-quote.
  714.  
  715.                   {$F+}
  716.                   procedure DoubleGrabber(var Keycode: word);
  717.                   begin
  718.                      if KeyCode = 34 then
  719.                         KeyCode := 39;
  720.                   end;
  721.                   {$F-}
  722.  
  723.                   begin
  724.                      .....
  725.                      AssignedPressedHook(DoubleGrabber);
  726.                      .....
  727.                   end.
  728.  
  729.          If you subsequently want to disable the pressed hook, use the following
  730.          statement:
  731.  
  732.                   Key.AssignPressedHook(NoInputPressedHook);
  733.  
  734.  
  735.  
  736. 6-16                                                                User's Guide
  737. --------------------------------------------------------------------------------
  738.  
  739. Hook Example
  740.  
  741.          The following demo program, DEMIN3.PAS, illustrates how to use the idle
  742.          and pressed hooks, and many other KeyOBJ features:
  743.          Program DemoInputThree;
  744.          {DEMIN3}
  745.  
  746.          Uses CRT,
  747.               totINPUT, totFAST, totMISC;
  748.          {$F+}
  749.          procedure ClockHook;
  750.          {}
  751.          begin
  752.             with Screen do
  753.             with Key do
  754.             begin
  755.                SetWinIgnore(true);
  756.                if GetCaps then
  757.                   WritePlain(40,24,'CAPS')
  758.                else
  759.                   WritePlain(40,24,'    ');
  760.                if GetNum then
  761.                   WritePlain(45,24,'NUM')
  762.                else
  763.                   WritePlain(45,24,'   ');
  764.                if GetScroll then
  765.                   WritePlain(50,24,'SCROLL')
  766.                else
  767.                   WritePlain(50,24,'      ');
  768.                if KeyPressed then
  769.                begin
  770.                   SetWinIgnore(false);
  771.                   exit;
  772.                end;
  773.                if AltPressed then
  774.                   WritePlain(60,24,'Alt')
  775.                else
  776.                   WritePlain(60,24,'   ');
  777.                if CtrlPressed then
  778.                   WritePlain(65,24,'Ctrl')
  779.                else
  780.                   WritePlain(65,24,'    ');
  781.                if LeftShiftPressed then
  782.                   WritePlain(70,24,'L-^X')
  783.                else
  784.                   WritePlain(70,24,'   ');
  785.                if RightShiftPressed then
  786.                   WritePlain(75,24,'R-^X')
  787.  
  788.  
  789. Keyboard & Mouse                                                            6-17
  790. --------------------------------------------------------------------------------
  791.  
  792.                else
  793.                   WritePlain(75,24,'   ');
  794.                if KeyPressed then
  795.                begin
  796.                   SetWinIgnore(false);
  797.                   exit;
  798.                end;
  799.                WritePlain(1,24,CurrentTime);
  800.                SetWinIgnore(false);
  801.             end;
  802.          end; {ClockHook}
  803.          {$F-}
  804.  
  805.          {$F+}
  806.          procedure MacroHook(var W:word);
  807.          {}
  808.          begin
  809.             case W of
  810.                286: begin
  811.                        Key.StuffBufferStr(' Apple '); {Alt-A}
  812.                        W := 0;
  813.                     end;
  814.                304: begin
  815.                        Key.StuffbufferStr(' Bravo '); {Alt-B}
  816.                        W := 0;
  817.                     end;
  818.                301: begin
  819.                        Key.StuffBuffer(27);           {Alt-X}
  820.                        W := 0;
  821.                     end;
  822.                315: begin
  823.                        Key.StuffbufferStr(' No help! '); {F1}
  824.                        W := 0;
  825.                     end;
  826.             end; {case}
  827.          end; {MacroHook}
  828.          {$F-}
  829.          begin
  830.             with Screen do
  831.             begin
  832.                Clear(31,' ');
  833.                PartClear(1,23,80,25,94,' ');
  834.                WritePlain(5,1,'Press any alpha characters,
  835.                                or Alt-A,B for macros.
  836.                                Esc or Alt-X to quit');
  837.                GotoXY(1,3);
  838.                with Key do
  839.                begin
  840.  
  841.  
  842. 6-18                                                                User's Guide
  843. --------------------------------------------------------------------------------
  844.  
  845.                   SetCaps(true);
  846.                   SetNum(true);
  847.                   SetScroll(true);
  848.                   AssignIdleHook(ClockHook);
  849.                   AssignPressedHook(MacroHook);
  850.                   Repeat
  851.                       GetInput;
  852.                       Write(LastChar);
  853.                   Until LastKey = 27;
  854.                   SetCaps(false);
  855.                   SetNum(false);
  856.                   SetScroll(false);
  857.                end;
  858.             end;
  859.          end.
  860.  
  861.  
  862.  
  863. Using the Mouse
  864.          The Toolkit provides full mouse support, and any mouse activity is
  865.          reported by the KeyOBJ object. Normally, you will not need to access
  866.          the mouse directly, but in case you need to, the totINPUT unit includes
  867.          the global instance MOUSE of type MouseOBJ. This instance can be used
  868.          to control the mouse cursor and check the status of the mouse buttons.
  869.  
  870.          All the Toolkit mouse support is for text mode only - the Toolkit does
  871.          not support the mouse in graphics mode.
  872.          The following methods can be used to control the mouse cursor and check
  873.          the mouse status:
  874.  
  875.  
  876.          Installed: boolean;
  877.          Returns true if a mouse and mouse driver are installed.
  878.  
  879.  
  880.          Visible: boolean;
  881.          Returns true if the mouse cursor is visible on the display.
  882.  
  883.  
  884.          Hide;
  885.          Hides the mouse cursor.
  886.  
  887.  
  888.          Show;
  889.          Displays the mouse cursor.
  890.  
  891.  
  892.          Move(X,Y:integer);
  893.  
  894.  
  895.  
  896. Keyboard & Mouse                                                            6-19
  897. --------------------------------------------------------------------------------
  898.  
  899.          Moves the mouse cursor to the coordinates (X,Y). Note this command
  900.          ignores the current window setting.
  901.  
  902.  
  903.          Confine(X1,Y1,X2,Y2:byte);
  904.          Restricts the mouse so that it can only move within the coordinates
  905.          (X1,Y1) to (X2,Y2).
  906.  
  907.  
  908.          Location(var X,Y:byte);
  909.          Updates the variables X and Y with the current location coordinates of
  910.          the mouse.
  911.  
  912.  
  913.          Status(var L,C,R:boolean; var X,Y);
  914.          Updates the L,C,R boolean variables to true if any of the Left, Center,
  915.          or Right mouse buttons are depressed, and updates the variables X and Y
  916.          with the current mouse location.
  917.  
  918.  
  919.          Pressed(Button:integer; var X,Y:byte): byte;
  920.          Returns the number of times the specified button has been pressed since
  921.          the function was last called. Button values of 0,1 and 2 represent the
  922.          Left, Right and Center buttons respectively. The variables X and Y are
  923.          updated with the coordinates of the mouse the last time the button was
  924.          pressed.
  925.  
  926.  
  927.          Released(Button:integer; var X,Y:byte):byte;
  928.          Returns the number of times the specified button has been released
  929.          since the function was last called. Button values of 0,1 and 2 repre-
  930.          sent the Left, Right and Center buttons respectively. The variables X
  931.          and Y are updated with the coordinates of the mouse the last time the
  932.          button was released.
  933.  
  934.  
  935.          GetButtons: byte;
  936.          Returns the number of buttons installed on the mouse.
  937.  
  938.  
  939.          SetMouseCursorStyle(OrdChar,Attr:byte);
  940.          Sets the mouse cursor to the character represented by the ASCII value
  941.          OrdChar. The second parameter controls the display attribute of the
  942.          mouse cursor. If a zero is specified, the Toolkit uses the standard
  943.          mouse device driver technique, which changes color based on the under-
  944.          lying screen attribute to ensure maximum contrast. If a non-zero
  945.          attribute value is specified, the mouse cursor will be displayed in the
  946.          specified attribute regardless of the screen display attributes.
  947.  
  948.  
  949. 6-20                                                                User's Guide
  950. --------------------------------------------------------------------------------
  951.  
  952.          SetLeft(On:boolean);
  953.  
  954.          The de facto standard in the industry is for the left button to be the
  955.          "do it" or "enter" button, and this is the Toolkit default. Use the
  956.          method SetLeft to control whether the left button or the right button
  957.          is used as the action button. Pass a TRUE parameter to use the left, or
  958.          a FALSE parameter to use the right.
  959.  
  960.          Reset;
  961.  
  962.          This method calls the mouse reset interrupt. The mouse is set back to
  963.          the center of the display, the cursor style is set back to the default,
  964.          and the mouse cursor is hidden.
  965.  
  966.  
  967.          Listed below is the mouse demo program DEMIN4.PAS, followed by figure
  968.          6.1 which illustrates the output from the program.
  969.          Program DemoInputFour;
  970.          {DEMIN4}
  971.  
  972.          Uses CRT,
  973.               totINPUT, totFAST, totSTR;
  974.          Var
  975.            Ch : char;
  976.            L,C,R,OldL,OldC,OldR: boolean;
  977.            X,Y,OldX,OldY: byte;
  978.  
  979.          begin
  980.             Clrscr;
  981.             with Mouse do
  982.             begin
  983.                if not Installed then
  984.                begin
  985.                   Writeln('This demo will only function
  986.                            on systems equipped with a mouse');
  987.                end
  988.                else
  989.                begin
  990.                   WriteLn('You have a ',GetButtons,' button mouse!');
  991.                   Writeln('Press: C to confine the mouse');
  992.                   Writeln('       U to unconfine the mouse');
  993.                   Writeln('       L to change the mouse cursor');
  994.                   Writeln('       R to reset mouse');
  995.                   Writeln('       H to hide the mouse');
  996.                   Writeln('       S to show the mouse');
  997.                   Writeln('       any mouse button');
  998.                   Writeln('       Esc to quit');
  999.                   Screen.FillBox(15,10,65,20,30,1);
  1000.                   Show;
  1001.  
  1002. Keyboard & Mouse                                                            6-21
  1003. --------------------------------------------------------------------------------
  1004.  
  1005.                   repeat
  1006.                      with Screen do
  1007.                      repeat
  1008.                         Status(L,C,R,X,Y);
  1009.                         if OldL <> L then
  1010.                            if L then
  1011.                               WriteAT(20,11,30,'Left Button')
  1012.                            else
  1013.                               WriteAT(20,11,30,'           ');
  1014.                         if OldR <> R then
  1015.                            if R then
  1016.                               WriteAT(20,12,30,'Right Button')
  1017.                            else
  1018.                               WriteAT(20,12,30,'            ');
  1019.                         if OldC <> C then
  1020.                            if C then
  1021.                               WriteAT(20,13,30,'Middle Button')
  1022.                            else
  1023.                               WriteAT(20,13,30,'             ');
  1024.                         if OldX <> X then
  1025.                            WriteAT(20,15,30,inttostr(X)+' ');
  1026.                         if OldY <> Y then
  1027.                             WriteAT(20,16,30,inttostr(Y)+' ');
  1028.                         OldL := L;
  1029.                         OldR := R;
  1030.                         OldC := C;
  1031.                         OldX := X;
  1032.                         OldY := Y;
  1033.                      until Key.KeyPressed;
  1034.                      Key.GetInput;
  1035.                      case upcase(Key.LastChar) of
  1036.                         'C': Confine(15,10,65,20);
  1037.                         'U': Confine(1,1,80,25);
  1038.                         'L': SetMouseCursorStyle(random(200)+56,0);
  1039.                         'H': Hide;
  1040.                         'S': Show;
  1041.                         'R': begin
  1042.                                 Hide;
  1043.                                 Reset;
  1044.                                 Show;
  1045.                              end;
  1046.                      end; {case}
  1047.                   until Key.LastKey = 27;
  1048.                   Hide;
  1049.                end;
  1050.                GotoXY(1,23);
  1051.             end;
  1052.          end.
  1053.  
  1054.  
  1055.  
  1056. 6-22                                                                User's Guide
  1057. --------------------------------------------------------------------------------
  1058.  
  1059. Figure 6.1                                                              [SCREEN]
  1060. Using the
  1061. MOUSE Object
  1062.